﻿namespace Blaze.Framework.Loaders
{
    using System;
    using System.Collections;
    using System.IO;

    /// <summary>
    /// 以二进制方式加载文件数据。
    /// </summary>
    public sealed class BinaryLoader : AssetLoaderBase
    {
        /// <summary>
        /// 获取加载器加载出来的字节数组。
        /// </summary>
        public byte[] Bytes
        {
            get { return Result as byte[]; }
        }

        /// <summary>
        /// 获取加载进度。
        /// </summary>
        public override float Progress
        {
            get { return mProgress; }
        }

        /// <summary>
        /// 当加载器启动时调用此方法。
        /// </summary>
        protected override void OnStart()
        {
            switch (Mode)
            {
                case LoadAssetMode.Sync:
                    var bytes = load(Uri);
                    Finish(null, bytes);
                    break;
                case LoadAssetMode.Async:
                    CoroutineManager.StartNew(loadAsync());
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        /// <summary>
        /// 加载指定路径下的文件。
        /// </summary>
        /// <param name="relativePath">相对路径</param>
        private static byte[] load(string relativePath)
        {
            byte[] ret;
            //优先从下载目录加载
            var path = $"{PathUtility.PersistentDataPath}/{relativePath}";
            if (File.Exists(path))
            {
                ret = File.ReadAllBytes(path);
                return ret;
            }

            //其次从StreamingAssets目录加载
            ret = StreamingAssets.Load(relativePath);
            if (ret != null && ret.Length > 0)
                return ret;
            return null;
        }

        private IEnumerator loadAsync()
        {
            var wwwLoader = AssetLoaderPool.Get<UnityWebRequestLoader>(Uri).SetMode(Mode).FluentStart();
            while (!wwwLoader.IsDone)
            {
                mProgress = wwwLoader.Progress;
                yield return null;
            }

            if (wwwLoader.IsOk)
                Finish(null, wwwLoader.Bytes);
            else
                Finish(wwwLoader.Error, null);
            AssetLoaderPool.Put(wwwLoader);
        }

        private float mProgress;
    }
}